package com.sinosoft.dsp.persistence.businessconcept.facade;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;

import com.sinosoft.builder.templates.concept.CodeType;
import com.sinosoft.builder.templates.concept.CodeValueObjectRef;
import com.sinosoft.builder.templates.concept.NamingElement;
import com.sinosoft.dsp.platform.components.portal.iteration.ISinoTreeDataObject;
import com.sinosoft.dsp.platform.components.portal.iteration.SinoTreeDataObject;
import com.sinosoft.dsp.system.core.log.Log;
import com.sinosoft.dsp.system.utils.Const;

public class CodeFacade extends SinoTreeDataObject implements ICodeFacade {

	private static final long serialVersionUID = 1124378707831589483L;

	private static final Log log = Log.getLog(CodeFacade.class.getName());

	private List<CodeValueObjectRef> refs;

	private List<NamingElement> names;

	public CodeFacade(CodeType ct) {
		this.names = ct.getNamingElement();
		this.refs = ct.getCodeValueObjectRef();
		this.setId(ct.getId());
	}

	@Override
	public ICodeFacade setCodeValueObjectRef(List<CodeValueObjectRef> ref) {
		LinkedList<CodeValueObjectRef> result = new LinkedList<CodeValueObjectRef>();
		for (CodeValueObjectRef cv : ref) {
			int index = 0;
			for (CodeValueObjectRef rcv : result) {
				// 待插入值小于等于当前值
				if (cv.getCreateTime().compare(rcv.getCreateTime()) <= 0) {
					result.add(index, cv);
					break;
				}
				index++;
			}
			if (index == result.size()) {
				result.addLast(cv);
			}
		}
		this.refs = result;
		return this;
	}

	@Override
	public ICodeFacade setNamingElement(List<NamingElement> names) {
		LinkedList<NamingElement> result = new LinkedList<NamingElement>();
		for (NamingElement ne : names) {
			int index = 0;
			for (NamingElement rne : result) {
				// 待插入值小于等于当前值
				if (ne.getChangedTime().compare(rne.getChangedTime()) <= 0) {
					result.add(index, ne);
					break;
				}
				index++;
			}
			if (index == result.size()) {
				result.addLast(ne);
			}
		}
		this.names = result;
		return this;
	}

	@Override
	public String getName() {
		NamingElement ne = getNamingElement();
		if (ne != null) {
			String name = ne.getAbbreviationName();
			if (Const.isEmpty(name)) {
				name = ne.getFullName();
			}
			return name;
		}
		return null;
	}

	@Override
	public String getName(Calendar date) {
		if (date == null) {
			return getName();
		}
		NamingElement ne = getNamingElement(date);
		if (ne != null) {
			String name = ne.getAbbreviationName();
			if (Const.isEmpty(name)) {
				name = ne.getFullName();
			}
			return name;
		}
		return null;
	}

	@Override
	public String getAlt() {
		NamingElement ne = getNamingElement();
		if (ne != null)
			return ne.getFullName();
		return null;
	}

	@Override
	public String getAlt(Calendar date) {
		if (date == null) {
			return getAlt();
		}
		NamingElement ne = getNamingElement(date);
		if (ne != null)
			return ne.getFullName();
		return null;
	}

	@Override
	public NamingElement getNamingElement() {
		if (this.names != null && this.names.size() > 0)
			return this.names.get(this.names.size() - 1);
		return null;
	}

	@Override
	public NamingElement getNamingElement(Calendar date) {
		if (date == null) {
			return getNamingElement();
		}
		if (this.names != null && this.names.size() > 0) {
			int index = 0;
			for (NamingElement ne : names) {
				if (ne.getChangedTime().toGregorianCalendar().compareTo(date) > 0)
					break;
				else
					index++;
			}
			index--;
			if (index > -1) {
				return this.names.get(index);
			}
		}
		return null;
	}

	@Override
	public Boolean isValid() {
		Calendar c = Calendar.getInstance();
		CodeValueObjectRef ref = getCodeValueObjectRef();
		if (ref == null) {
			return false;
		}
		if (ref.getCreateTime().toGregorianCalendar().compareTo(c) <= 0) {
			if (ref.getEndTime() != null
					&& ref.getEndTime().toGregorianCalendar().compareTo(c) <= 0) {
				return false;
			}
			return true;
		}
		return false;
	}

	@Override
	public Boolean isValid(Calendar c) {
		if (c == null) {
			return isValid();
		}
		CodeValueObjectRef ref = getCodeValueObjectRef(c);
		if (ref == null) {
			return false;
		}
		if (ref.getCreateTime().toGregorianCalendar().compareTo(c) <= 0) {
			if (ref.getEndTime() != null
					&& ref.getEndTime().toGregorianCalendar().compareTo(c) <= 0) {
				return false;
			}
			return true;
		}
		return false;
	}

	@Override
	public String getValue() {
		CodeValueObjectRef ref = getCodeValueObjectRef();
		return (ref != null) ? ref.getRef().getValue() : null;
	}

	@Override
	public String getValue(Calendar date) {
		if (date == null) {
			return getValue();
		}
		CodeValueObjectRef ref = getCodeValueObjectRef(date);
		return (ref != null) ? ref.getRef().getValue() : null;
	}

	@Override
	public CodeValueObjectRef getCodeValueObjectRef() {
		if (this.refs != null && this.refs.size() > 0) {
			// 获得最后一个值
			CodeValueObjectRef last = this.refs.get(this.refs.size() - 1);
			if (checkValid(last, Calendar.getInstance())) {
				return last;
			}
		}
		return null;
	}

	@Override
	public CodeValueObjectRef getCodeValueObjectRef(Calendar date) {
		if (date == null) {
			return getCodeValueObjectRef();
		}
		if (this.refs != null && this.refs.size() > 0) {
			int index = 0;
			for (CodeValueObjectRef vo : refs) {
				// 创建时间大于给定时间
				if (vo.getCreateTime().toGregorianCalendar().compareTo(date) > 0)
					break;
				else
					index++;
			}
			index--;
			if (index > -1) {
				if (checkValid(this.refs.get(index), date)) {
					return this.refs.get(index);
				}
			}
		}
		return null;
	}

	@Override
	public CodeValueObjectRef[] getValidCodeValueObjectRef() {
		return getValidCodeValueObjectRef(Calendar.getInstance());
	}

	@Override
	public CodeValueObjectRef[] getValidCodeValueObjectRef(Calendar date) {
		if (date == null) {
			return getValidCodeValueObjectRef();
		}
		if (this.refs != null && this.refs.size() > 0) {
			List<CodeValueObjectRef> list = new ArrayList<CodeValueObjectRef>();
			for (CodeValueObjectRef vo : refs) {
				if (checkValid(vo, date)) {
					list.add(vo);
				}
			}
			if (list.size() > 0) {
				return list.toArray(new CodeValueObjectRef[list.size()]);
			}
		}
		return null;
	}

	private boolean checkValid(CodeValueObjectRef ref, Calendar date) {
		if (date == null) {
			date = Calendar.getInstance();
		}
		// 创建时间小于等于给定时间
		if (ref.getCreateTime().toGregorianCalendar().compareTo(date) <= 0) {
			if (ref.getEndTime() != null) {
				// 结束时间大于给定时间
				if (ref.getEndTime().toGregorianCalendar().compareTo(date) > 0) {
					return true;
				}
			} else {
				return true;
			}
		}
		return false;
	}

	@Override
	public List<CodeValueObjectRef> getRefs() {
		return refs;
	}

	@Override
	public List<NamingElement> getNames() {
		return names;
	}

	@Override
	public ISinoTreeDataObject createTreeDataObject() {
		ISinoTreeDataObject t = new SinoTreeDataObject();
		t.setId(this.getId());
		t.setName(this.getName());
		t.setAlt(this.getAlt());
		t.setValue(this.getValue());
		t.setType(ICodeFacade.CODE_NODE_TYPE);
		log.debug("创建树形值对象，ID：" + this.getId() + "名称为：" + this.getName()
				+ "，全称：" + this.getAlt());
		return t;
	}

	@Override
	public ISinoTreeDataObject createTreeDataObject(Calendar date) {
		if (date == null) {
			return createTreeDataObject();
		}
		ISinoTreeDataObject t = new SinoTreeDataObject();
		t.setId(this.getId());
		t.setName(this.getName(date));
		t.setAlt(this.getAlt(date));
		t.setValue(this.getValue(date));
		t.setType(ICodeFacade.CODE_NODE_TYPE);
		log.debug("创建树形值对象，ID：" + this.getId() + "名称为：" + this.getName(date)
				+ "，全称：" + this.getAlt(date));
		return t;
	}

}
